package com.atguigu.gmall.cart.biz.impl;

import com.alibaba.fastjson.JSON;
import com.atguigu.gmall.cart.biz.CartBizService;
import com.atguigu.gmall.cart.entity.CartItem;
import com.atguigu.gmall.cart.vo.AddCartSuccessVo;
import com.atguigu.gmall.common.constant.GmallConstant;
import com.atguigu.gmall.common.execption.GmallException;
import com.atguigu.gmall.common.feign.interceptor.AuthUserInfo;
import com.atguigu.gmall.common.feign.product.SkuFeignClient;
import com.atguigu.gmall.common.feign.util.AuthUserInfoUtils;
import com.atguigu.gmall.common.result.Result;
import com.atguigu.gmall.common.result.ResultCodeEnum;
import com.atguigu.gmall.product.entity.SkuInfo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Service
@Slf4j
public class CartBizServiceImpl implements CartBizService {

    @Autowired
    private RedisTemplate<String , String> redisTemplate ;

    @Autowired
    private SkuFeignClient skuFeignClient ;



    @Override
    public AddCartSuccessVo addCart(Long skuId, Integer skuNum) {
        log.info("CartBizServiceImpl...addCart方法执行了...");

        // 构建Redis数据key
        String  cartRedisKey = buildRedisKey() ;

        // 把商品添加购物车中
        // 判断当前要添加的商品在购物车是否存在，如果不存在直接创建一个购物项数据对象，然后把购物项添加到购物车中
        Boolean result = redisTemplate.opsForHash().hasKey(cartRedisKey, String.valueOf(skuId));

        // 远程调用product微服务的接口，根据skuId获取skuInfo数据
        Result<SkuInfo> skuInfoResult = skuFeignClient.findSkuInfoBySkuId(skuId);
        SkuInfo skuInfo = skuInfoResult.getData();


        if(result) {        // 如果已经存在，购物项的数量进行加操作
            //String.valueOf的作用是 将别的类型转换成String类型的字符串 这儿是把long类型的skuId转换成String类型的字符串
            String cartItemJSON = redisTemplate.opsForHash().get(cartRedisKey, String.valueOf(skuId)).toString();
            //JSON.parseObject，是将Json字符串转化为相应的对象 也就是CartItem对象
            CartItem cartItem = JSON.parseObject(cartItemJSON, CartItem.class);
            cartItem.setSkuNum(cartItem.getSkuNum() + skuNum);

            // 购买数量的限制
            Integer itemSkuNum = cartItem.getSkuNum();
            if (itemSkuNum > 10){
                cartItem.setSkuNum(10);
            }

            //JSON.toJSONString则是将对象(cartItem)转化为Json字符串
            redisTemplate.opsForHash().put(cartRedisKey , String.valueOf(skuId) , JSON.toJSONString(cartItem));

        }else {  // 如果不存在直接创建一个购物项数据对象，然后把购物项添加到购物车中

            // 获取当前购物车中购物项的数量
            Long count = redisTemplate.opsForHash().size(cartRedisKey);
            if (count >= 3){
                throw new GmallException(ResultCodeEnum.CART_ITEM_NUMBER_ERROR) ;
            }

            CartItem cartItem = new CartItem() ;
            cartItem.setId(skuId);
            cartItem.setSkuId(skuId);
            cartItem.setCartPrice(skuInfo.getPrice());
            cartItem.setSkuPrice(skuInfo.getPrice());
            if(skuNum > 10) {           // 购买数量的限制
                skuNum = 10 ;
            }
            cartItem.setSkuNum(skuNum);
            cartItem.setImgUrl(skuInfo.getSkuDefaultImg());
            cartItem.setSkuName(skuInfo.getSkuName());
            cartItem.setIsChecked(1);
            cartItem.setCreateTime(new Date());
            cartItem.setUpdateTime(new Date());

            // 存储购物项数据到Redis中
            redisTemplate.opsForHash().put(cartRedisKey , String.valueOf(skuId) , JSON.toJSONString(cartItem));

        }

        // 构建响应结果
        AddCartSuccessVo addCartSuccessVo = new AddCartSuccessVo() ;
        addCartSuccessVo.setSkuInfo(skuInfo);
        addCartSuccessVo.setSkuNum(skuNum);

        //针对临时购物车设置过期时间
        String userId = AuthUserInfoUtils.getAuthUserInfo().getUserId();
        if (StringUtils.isEmpty(userId)){//说明用户没有登陆
            //对临时购物车进行过期时间设置
            Long expire = redisTemplate.getExpire(cartRedisKey);
            if (expire == -1){
                redisTemplate.expire(cartRedisKey , 30 , TimeUnit.DAYS) ;
            }
        }

        // 返回
        return addCartSuccessVo;
    }

    @Override
    public void deleteAllChecked() {
        String redisKey = buildRedisKey();
        //获取该购物车中的所有商品数据
        List<Object> values = redisTemplate.opsForHash().values(redisKey);

        //遍历List集合获取每一个购物项数据 判断isChecked是否为1 是1就删除
        values.stream().forEach(obj -> {
            //先拿到他的JSON字符串对象
            String cartItemJSON = obj.toString();
            CartItem cartItem = JSON.parseObject(cartItemJSON, CartItem.class);
            if (cartItem.getIsChecked() == 1){
                redisTemplate.opsForHash().delete(redisKey , String.valueOf(cartItem.getSkuId()));
            }
        });
    }

    @Override
    public List<CartItem> findAllSelectedCartItem() {

        //构建redis的数据key
        String userId = AuthUserInfoUtils.getAuthUserInfo().getUserId();
        String rediskey = GmallConstant.REDIS_CART_PRE + userId;

        //从redis中获取选中的购物项数据
        List<CartItem> cartItemList = redisTemplate.opsForHash().values(rediskey).stream().map(obj -> {
            String cartItemJSON = obj.toString();
            CartItem cartItem = JSON.parseObject(cartItemJSON, CartItem.class);
            return cartItem;
        }).filter(cartItem -> cartItem.getIsChecked() == 1).collect(Collectors.toList());

        return cartItemList;
    }

    private String buildRedisKey() {

        //获取用户的id或者临时用户的id
        AuthUserInfo authUserInfo = AuthUserInfoUtils.getAuthUserInfo();
        if(authUserInfo != null) {
            String userId = authUserInfo.getUserId();
            String userTempId = authUserInfo.getUserTempId();
            if(!StringUtils.isEmpty(userId)) {
                return GmallConstant.REDIS_CART_PRE + userId ;
            }else {
                return GmallConstant.REDIS_CART_PRE + userTempId ;
            }
        }else {
            return null ;
        }

    }

}




















